package com.bdqn.petmalldemo.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bdqn.petmalldemo.bo.OrderAddBo;
import com.bdqn.petmalldemo.common.KetaiException;
import com.bdqn.petmalldemo.common.ResultCodeEnum;
import com.bdqn.petmalldemo.common.SystemConstants;
import com.bdqn.petmalldemo.common.TokenCache;
import com.bdqn.petmalldemo.entity.*;
import com.bdqn.petmalldemo.mapper.OrderMapper;
import com.bdqn.petmalldemo.mapper.ProductMapper;
import com.bdqn.petmalldemo.mapper.ShippingMapper;
import com.bdqn.petmalldemo.service.CartService;
import com.bdqn.petmalldemo.service.OrderDetailService;
import com.bdqn.petmalldemo.service.OrderService;
import com.bdqn.petmalldemo.vo.OrderVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author Lenovo
 * @since 2020-02-10
 */
@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    @Resource
    private ProductMapper productMapper;
    @Resource
    private ShippingMapper shippingMapper;
    @Resource
    private CartService cartService;
    @Resource
    private OrderDetailService orderDetailService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addOrder(OrderAddBo orderAddBo) {
        //1.生成条件的检验
        //1.1 必须指定收货地址
        if (StringUtils.isEmpty(orderAddBo.getShippingId())) {
            throw new KetaiException(ResultCodeEnum.ADDRESS_NULL);
        }
        //1.2、必须有充足库存,根据当前登录的用户查询相关的购物车信息,然后再与当商品的库存进行比对
        User user = JSONObject.parseObject(TokenCache.get(orderAddBo.getToken()), User.class);
        QueryWrapper<Cart> cartQueryWrapper = new QueryWrapper<>();
        cartQueryWrapper.eq("user_id",user.getId());
        List<Cart> cartList = cartService.list(cartQueryWrapper);
        //当前用户的购物车中商品Id集合
        List<String> productIdList = cartList.stream().map(Cart::getProductId).collect(Collectors.toList());
        QueryWrapper<Product> productQueryWrapper = new QueryWrapper<>();
        productQueryWrapper.in(!productIdList.isEmpty(),"id",productIdList);
        List<Product>productList=productMapper.selectList(productQueryWrapper);

        //当前购物车中的商品总价格
        BigDecimal productPriceAmount=BigDecimal.ZERO;

        //订单详情列表
        List<OrderDetail> orderDetailList=new ArrayList<>(10);

        //生成orderNo
        String orderNo=LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))
                +String.valueOf(RandomUtils.nextInt(100000,999999));

        //orderId
        String orderId=UUID.randomUUID().toString().replace("-","");

        for (Cart cart:cartList) {
            OrderDetail orderDetail=new OrderDetail();
            for (Product product:productList) {
                //判断当前的商品库存是否足够
                if (cart.getProductId().equals(product.getId())) {
                    //计算当前商品的总价,数量*单价
                    BigDecimal productPrice = BigDecimal.valueOf(cart.getQuantity()).multiply(product.getPrice());
                    productPriceAmount = productPriceAmount.add(productPrice);
                    if (cart.getQuantity() > product.getStock()) {
                        throw new KetaiException(ResultCodeEnum.PURCHASE_QUANTITY_IS_GREATER_THAN_INVENTORY_QUANTITY);
                    }
                    orderDetail.setProductId(product.getId())
                            .setUnitPrice(product.getPrice())
                            .setCategoryId(product.getCategoryId())
                            .setSellerId(product.getUserId())
                            .setSellerUsername(product.getUserName())
                            .setProductImage(product.getMainImage())
                            .setProductName(product.getName()).setOrderNo(orderNo)
                            .setUserId(cart.getUserId())
                            .setUsername(user.getUsername())
                            .setQuantity(cart.getQuantity())
                            .setTotalPrice(productPriceAmount)
                            .setOrderId(orderId);
                    orderDetailList.add(orderDetail);
                    //完成库存扣减
                    productMapper.updateById(product.setStock(product.getStock() - cart.getQuantity()));
                }
            }
        }
        //新增订单详情
        orderDetailService.saveBatch(orderDetailList);
        //查询收货信息
        Shipping shipping = shippingMapper.selectById(orderAddBo.getShippingId());
        //开始生成订单
        Order order = new Order();

        order.setOrderNo(orderNo)
                .setId(orderId)
            .setUserId(user.getId())
                .setUsername(user.getUsername())
              .setProductPriceAmount(productPriceAmount)
               .setFreight(SystemConstants.FREIGHT)
                .setPayment(productPriceAmount.add(SystemConstants.FREIGHT))
                .setShippingAddress(shipping.getAddress())
                .setShippingName(shipping.getName())
                .setShippingPhone(shipping.getPhone())
                .setShippingZipCode(shipping.getZipCode())
                .setRemark(orderAddBo.getRemark())
                .setStatus(SystemConstants.ORDER_STATUS.UNPAID)
                //订单超时三十分钟
                .setTimeoutTime(LocalDateTime.now().plusMinutes(30L));
        //执行新增
        baseMapper.insert(order);

        //清空购物车
        cartService.removeByIds(cartList.stream().map(Cart::getId).distinct().collect(Collectors.toList()));
    }

    @Override
    public Map<String, Object> searchOrder(String userId, Integer currentPage, Integer pageSize) {
        IPage<Order> page = new Page<>(StringUtils.isEmpty(currentPage) ?1 : currentPage,
                StringUtils.isEmpty(pageSize)?10 : pageSize);
        QueryWrapper<Order> orderQueryWrapper = new QueryWrapper<>();
        //根据UserId是否为空实现动态查询
        orderQueryWrapper.eq(StringUtils.hasText(userId),"user_id",userId);
        //执行分页查询
        baseMapper.selectPage(page,orderQueryWrapper);
        //取出订单列表,然后再根据订单列表查询订单详情
        List<Order> orderList = page.getRecords();
        if (CollectionUtils.isEmpty(orderList)){
            return new HashMap<>(16);
        }
        //循环查询每个订单记录下面的订单详情,并进行数据处理
        List<OrderVo>orderVoList=new ArrayList<>(orderList.size());
        orderList.forEach(order -> {
            OrderVo orderVo = new OrderVo();
            BeanUtils.copyProperties(order,orderVo);
            QueryWrapper<OrderDetail> orderDetailQueryWrapper = new QueryWrapper<>();
            orderDetailQueryWrapper.eq("order_id",order.getId());
            List<OrderDetail> orderDetailList = orderDetailService.getBaseMapper().selectList(orderDetailQueryWrapper);
            orderVo.setOrderDetailList(orderDetailList);
            orderVoList.add(orderVo);
        });
        //返回数据的处理
        Map<String,Object>map=new HashMap<>(16);
        map.put("list",orderVoList);
        map.put("pages",page.getPages());
        map.put("pageNum",page.getCurrent());
        map.put("total",page.getTotal());
        return map;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void cancelOrder(String orderId) {
        //1.查询订单信息及订单详情
        Order order = baseMapper.selectById(orderId);
        //先判断当前订单是否为未付款状态
        if (!SystemConstants.ORDER_STATUS.UNPAID.equals(order.getStatus())) {
            throw new KetaiException(ResultCodeEnum.ORDER_STATUS_ERROR);
        }
        QueryWrapper<OrderDetail> orderDetailQueryWrapper = new QueryWrapper<>();
        orderDetailQueryWrapper.eq("order_id",orderId);
        List<OrderDetail> orderDetailList = orderDetailService.list(orderDetailQueryWrapper);
        //2.回退当前订单中商品的库存
        if (CollectionUtils.isEmpty(orderDetailList)) {
            throw new KetaiException(ResultCodeEnum.DATA_NULL);
        }
        orderDetailList.forEach(orderDetail -> {
            //执行库存回退
            Product product = productMapper.selectById(orderDetail.getProductId());
            product.setStock(product.getStock()+orderDetail.getQuantity());
            productMapper.updateById(product);
        });
        //3.修改商品的状态
        baseMapper.updateById(order.setStatus(SystemConstants.ORDER_STATUS.CANCEL));
    }

    /**
     * 定时任务完成订单关闭
     */
    @Scheduled(cron = "0 0/5 * * * *")
    public void closeOrder(){
        log.info("开始订单关闭定时任务....");
        //1.查询所有状态为已完成的订单
        QueryWrapper<Order> orderQueryWrapper = new QueryWrapper<>();
        orderQueryWrapper.eq("status",SystemConstants.ORDER_STATUS.END);
        List<Order> orderList = baseMapper.selectList(orderQueryWrapper);
        if (!CollectionUtils.isEmpty(orderList)) {
            orderList.forEach(order -> {
                //2.修改当前订单状态为已关闭
                order.setStatus(SystemConstants.ORDER_STATUS.CLOSED);
                baseMapper.updateById(order);
            });
        }
    }
    /**
     * 订单超时定时任务
     */
    //@Scheduled(cron = "0/15 * * * * *")
    public void timeOutOrder(){
        log.info("开始订单超时定时任务....");
        LocalDateTime now = LocalDateTime.now();
        //获取系统当前时间大于超时时间的订单
        QueryWrapper<Order> orderQueryWrapper = new QueryWrapper<>();
        orderQueryWrapper.lt("timeout_time",now)
                .eq("status",SystemConstants.ORDER_STATUS.UNPAID);
        List<Order> orderList = baseMapper.selectList(orderQueryWrapper);
        if (!CollectionUtils.isEmpty(orderList)) {
            //修改当前订单状态为已超时
            orderList.forEach(order -> {
                order.setStatus(SystemConstants.ORDER_STATUS.TIME_OUT);
                baseMapper.updateById(order);
                //将订单中的商品执行库存的回退
                QueryWrapper<OrderDetail> orderDetailQueryWrapper = new QueryWrapper<>();
                orderDetailQueryWrapper.eq("order_id",order.getId());
                List<OrderDetail> orderDetailList = orderDetailService.list(orderDetailQueryWrapper);
                if (!CollectionUtils.isEmpty(orderDetailList)) {
                    orderDetailList.forEach(orderDetail -> {
                        Product product = productMapper.selectById(orderDetail.getProductId());
                        product.setStock(product.getStock()+orderDetail.getQuantity());
                        productMapper.updateById(product);
                    });
                }

            });
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void sendAll(String orderId) {
        //判断当前订单已经完成付款
        Order order = baseMapper.selectById(orderId);
        if (order==null) {
            throw new KetaiException(ResultCodeEnum.DATA_NULL);
        }
        //判断订单状态
        if (!order.getStatus().equals(SystemConstants.ORDER_STATUS.PAID)) {
            throw new KetaiException(ResultCodeEnum.ORDER_STATUS_EXCEPTION);
        }
        //更新当前订单状态(全部发货)
        order.setStatus(SystemConstants.ORDER_STATUS.SHIP_ALL);
        baseMapper.updateById(order);
        QueryWrapper<OrderDetail> orderDetailQueryWrapper = new QueryWrapper<>();
        orderDetailQueryWrapper.eq("order_id",orderId);
        List<OrderDetail> list = orderDetailService.list(orderDetailQueryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            throw new KetaiException(ResultCodeEnum.DATA_NULL);
        }
        list.forEach(orderDetail -> {
            orderDetail.setSendStatus(2);
            orderDetail.setSendTime(LocalDateTime.now());
        });
        //批量更新
        orderDetailService.updateBatchById(list);
    }

    @Override
    public void complete(String orderId) {
        Order order = baseMapper.selectById(orderId);
        //订单数据不能为空
        if (order==null) {
            throw  new  KetaiException(ResultCodeEnum.DATA_NULL);
        }
        //判断当前订单的状态是否为全部发货
        if (SystemConstants.ORDER_STATUS.SHIP_ALL.equals(order.getStatus())) {
            //确认收货,也就是将当前订单的状态设为完成
            baseMapper.updateById(order.setStatus(SystemConstants.ORDER_STATUS.END));
        }

    }
}
